package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *
 * @author wfyn
 * @date 2023/10/5
 */
@Slf4j
@Service
public class SetmealServiceImpl implements SetmealService {


    @Autowired
    SetmealMapper setmealMapper;
    @Autowired
    SetmealDishMapper setmealDishMapper;
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    DishMapper dishMapper;
    @Autowired
    OrderMapper  orderMapper;


    /**
     * 更新套餐
     * @param setmealDTO 套餐DTO对象
     */
    @Transactional
    public void updateWithDish(SetmealDTO setmealDTO) {
        // 创建Setmeal对象
        Setmeal setmeal = new Setmeal();

        // 将SetmealDTO属性拷贝到Setmeal对象中
        BeanUtils.copyProperties(setmealDTO, setmeal);

        // 更新套餐信息
        setmealMapper.update(setmeal);

        // 获取套餐ID
        Long id = setmealDTO.getId();

        // 根据套餐ID删除与菜品的关联数据
        setmealDishMapper.deleteBySetmealId(id);

        // 获取套餐的菜品列表
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();

        if (setmealDishes != null && !setmealDishes.isEmpty()) {
            // 设置套餐ID
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(id));

            // 批量插入套餐菜品关联数据
            setmealDishMapper.insertBatch(setmealDishes);
        }
    }



    /**
     * 保存套餐及相关菜品信息
     *
     * @param setmealDTO 套餐DTO对象
     */
    @Transactional
    public void saveWithDish(SetmealDTO setmealDTO) {
        // 创建套餐对象并拷贝属性
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);

        // 插入套餐信息到数据库
        setmealMapper.insert(setmeal);

        // 获取新插入套餐的ID
        Long setmealId = setmeal.getId();

        // 获取套餐包含的菜品列表
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();

        // 设置菜品关联的套餐ID为新插入的套餐ID
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmealId));

        // 批量插入菜品信息到数据库
        setmealDishMapper.insertBatch(setmealDishes);
    }



    /**
     * 批量删除套餐及其相关菜品信息
     *
     * @param ids 待删除套餐的ID列表
     */
    @Transactional
    public void deleteBatch(List<Long> ids) {
        for (Long id : ids) {
            // 根据套餐ID查询套餐信息
            Setmeal setmeal = setmealMapper.getById(id);

            // 如果套餐处于启用状态，则抛出异常，禁止删除
            if (Objects.equals(setmeal.getStatus(), StatusConstant.ENABLE)) {
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        }

        // 批量删除套餐信息
        setmealMapper.deleteBatch(ids);

        // 删除与待删除套餐关联的菜品信息
        setmealDishMapper.deleteBySetmealIds(ids);
    }



    /**
     * 分页查询套餐列表
     *
     * @param pageQueryDTO 套餐分页查询参数
     * @return 分页结果，包括总记录数和当前页的套餐列表
     */
    public PageResult pageQuery(SetmealPageQueryDTO pageQueryDTO) {
        // 使用分页插件，设置分页参数，包括当前页码和每页记录数
        PageHelper.startPage(pageQueryDTO.getPage(), pageQueryDTO.getPageSize());

        // 调用DAO层的方法查询套餐数据
        Page<SetmealVO> page = setmealMapper.pageQuery(pageQueryDTO);

        // 构建分页结果对象，包括总记录数和当前页的套餐列表
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 根据套餐ID获取套餐及相关菜品信息
     *
     * @param id 套餐ID
     * @return 包含套餐信息和相关菜品信息的数据对象
     */
    public SetmealVO getByIdWithSetmeal(Long id) {
        // 创建一个用于返回的套餐VO对象
        SetmealVO setmealVO = new SetmealVO();

        // 根据套餐ID查询套餐基本信息
        Setmeal setmeal = setmealMapper.getById(id);

        // 将套餐基本信息拷贝到套餐VO对象中
        BeanUtils.copyProperties(setmeal, setmealVO);

        // 根据套餐ID查询与套餐相关的菜品信息
        List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(setmeal.getId());

        // 设置套餐VO对象的菜品列表属性
        setmealVO.setSetmealDishes(setmealDishes);

        // 返回包含套餐信息和相关菜品信息的套餐VO对象
        return setmealVO;
    }

    /**
     * 启用或停用套餐
     *
     * @param status 套餐状态 (StatusConstant中定义了启用和停用的常量)
     * @param id     套餐ID
     */
    @Transactional
    public void startOrStop(Integer status, Long id) {
        // 根据套餐ID查询与套餐相关的菜品信息
        List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(id);

        // 如果要启用套餐
        if (Objects.equals(status, StatusConstant.ENABLE)) {
            // 遍历套餐关联的菜品列表
            setmealDishes.forEach(setmealDish -> {
                // 根据菜品ID查询菜品信息
                Dish dish = dishMapper.getById(setmealDish.getDishId());

                // 如果菜品的状态是停用，抛出异常，禁止启用套餐
                if (StatusConstant.DISABLE.equals(dish.getStatus())) {
                    throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
                }
            });
        }

        // 创建一个套餐对象，用于更新套餐的状态
        Setmeal setmeal = Setmeal.builder()
                .status(status)
                .id(id)
                .build();

        // 调用DAO层的方法更新套餐状态
        setmealMapper.update(setmeal);
    }
    /**
     * 条件查询
     * @param setmeal
     * @return
     */
    public List<SetmealVO> list(Setmeal setmeal) {


        List<Setmeal> list = setmealMapper.list(setmeal);

        List<SetmealVO> setmealVOList = list.stream().map(
                (item) ->
                {
                    SetmealVO setmealVO = new SetmealVO();
                    BeanUtils.copyProperties(item, setmealVO);
                    Integer saleCount=orderMapper.getSaleBySetmealId(setmealVO.getId());
                    saleCount= saleCount == null ? 0: saleCount;
                    setmealVO.setCopies(saleCount);
                    return setmealVO;
                }
        ).collect(Collectors.toList());

        return setmealVOList;
    }

    /**
     * 根据id查询菜品选项
     * @param id
     * @return
     */
    public List<DishItemVO> getDishItemById(Long id) {
        return setmealMapper.getDishItemBySetmealId(id);
    }

}
